home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Precision Software Appli…tions Silver Collection 4
/
Precision Software Applications Silver Collection Volume 4 (1993).iso
/
stats
/
chadyn.exe
/
YXPLOT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-08
|
21KB
|
676 lines
/* YXPLOT.C - routines to perform the same services as those in YPLOT.C
* but using the X windows library.
* Notes on this version:
* 1. no "core" copy of the picture is retained.
* 2. there is no printer support yet.
* Programmer: Eric Kostelich, Institute for Physical Science and Technology,
* University of Maryland, College Park 20742
*/
#define XINCLUDES
#include "yinclud.h"
#ifdef X11
/* ---------------------------------------------------------------------- */
/* BOOTCRT - redraws the screen according to the value of the gloval
* variable "boot". If boot == 0, then we clear the screen and allocate
* a "core" copy of the graphics screen. Otherwise, we do nothing.
* Note: this is a temporary version.
*/
boot_crt()
{
#ifdef NEW
XImage *coreimage;
#endif /* NEW */
int i;
ScreenConstants(); /* to fix up some constants */
IsCross0Set = NO; /* screen cross at y0 is not set */
IsCross1Set = NO; /* screen cross at yval is not set */
if(printer == 3)
bottomPrint();
#ifdef NEW
XClearWindow(x_dpy, x_window);
if(boot == 0) { /* allocate core copy and clear it */
if(x_core == (Pixmap) 0 &&
(x_core = XCreatePixmap(x_dpy, x_window, scrncols,
scrnrows, 1)) == (Pixmap) 0)
die("can't create core copy of graphics");
XFillRectangle(x_dpy, x_core, x_gcblank, 0, 0,
(unsigned) scrncols, (unsigned) scrnrows);
if(ScrnSec == 0) /* turn off window overlap prevention */
for(i = 0; i <= 4; i++)
windowflag[i] = OFF;
}
else { /* copy core image to screen */
coreimage = XGetImage(x_dpy, x_core, 0, 0, scrncols, scrnrows,
AllPlanes, XYPixmap);
XPutImage(x_dpy, x_window, x_gc, coreimage, 0, 0, 0, 0,
scrncols, scrnrows);
XDestroyImage(coreimage); /* to conserve memory */
}
#else /* temporary version */
if(boot == 0) {
XClearWindow(x_dpy, x_window);
if(ScrnSec == 0) /* turn off window overlap prevention */
for(i = 0; i <= 4; i++)
windowflag[i] = OFF;
}
#endif /* NEW */
if(boxx) /* draw a box if requested */
draw_box();
boot = 0;
return;
}
/* ---------------------------------------------------------------------- */
ScreenConstants()
{
X_Lo[ScrnSec] = X_lower;
X_Up[ScrnSec] = X_upper;
Y_Lo[ScrnSec] = Y_lower;
Y_Up[ScrnSec] = Y_upper;
xScrPix[ScrnSec] = scrncols / (X_upper - X_lower);/* for screen */
yScrPix[ScrnSec] = scrnrows / (Y_upper - Y_lower);
return;
}
/* ---------------------------------------------------------------------- */
/* FINDPIXEL - return a pointer to a POINT (integer point) which maps the
* floating point (x,y) to integer screen coordinates.
* Return NULL if (x,y) would fall outside the screen area.
* However, forgive a 1-pixel overflow.
* Note: this is a temporary version which returns NULL unless PICNUM
* refers to the screen.
*/
POINT *FindPixel(xval, yval, picnum)
double xval, yval;
int picnum;
{
static POINT scrnpt;
int xmax, ymax;
if(picnum == 1) { /* crt */
xmax = scrncols;
ymax = scrnrows;
scrnpt.x = xScrPix[ScrnSec] * (xval - X_lower);
if(scrnpt.x == xmax)
scrnpt.x--;
scrnpt.y = yScrPix[ScrnSec] * (Y_upper - yval);
if(scrnpt.y == ymax)
scrnpt.y--;
}
else
return(NULL);
if(scrnpt.x >= 0 && scrnpt.x < xmax && scrnpt.y >= 0
&& scrnpt.y < ymax) {
switch(ScrnSec) {
case UPPERLEFT:
scrnpt.x /= 2;
scrnpt.y /= 2;
break;
case UPPERRIGHT:
scrnpt.x = (scrnpt.x + xmax) / 2;
scrnpt.y /= 2;
break;
case LOWERLEFT:
scrnpt.x = scrnpt.x / 2;
scrnpt.y = (scrnpt.y + ymax) / 2;
break;
case LOWERRIGHT:
scrnpt.x = (scrnpt.x + xmax) / 2;
scrnpt.y = (scrnpt.y + ymax) / 2;
break;
}
return(&scrnpt);
}
else
return(NULL);
}
/* -------------------------------------------------------------------- */
/* PLOT - maps the point (xval, yval) in user coordinates to screen coordinates
* and plots the dot if it is within the screen boundaries. Otherwise
* it checks whether the point is too far away and sets single step mode
* as needed.
*/
plot(xval, yval)
double xval, yval;
{
POINT *p;
/* If we are outside the screen, then check that we're not
* so far away that we need to go to single step mode to
* prevent overflow.
*/
if((p = FindPixel(xval, yval, SCRN)) == NULL)
checkiterate(xval, yval);
else {
/* If the cross is not turned off, and the new dot to be plotted
* is in the cross, it will cause erased when the cross goes.
*/
if(IsCross0Set)
turnoff(BIGCROSS);
setPixel(p);
if(cross0flag) /* set using interrupt 'k' */
SetCross(BIGCROSS);
}
return;
}
/* -------------------------------------------------------------------- */
/* CHECKITERATE - Check whether a point, which is not in the window,
* is within "diameters[ScrnSec]" times the width and within
* "diameters[ScrnSec] times the height of the
* screen. If it is not close enough to the screen based on this
* criterion, the program is reset to SINGLE STEP mode to prevent
* overflow.
* Note: the check is done only if the value of DIAMETERS is > 0.
*/
checkiterate(xval, yval)
double xval, yval;
{
double d, xdif, ydif;
if((d = diameters[ScrnSec]) > 0.0) {
xdif = X_upper - X_lower;
ydif = Y_upper - Y_lower;
d *= (d + 1.0);
if((X_upper - xval) * (xval - X_lower) > d * xdif * xdif
|| (Y_upper - yval) * (Y_lower - yval) > d * ydif * ydif)
PlotComplaint(xval, yval);
}
return;
}
/* -------------------------------------------------------------------- */
/* PLOTCOMPLAINT - complain about points too far away.
*/
PlotComplaint(xval, yval)
double xval, yval;
{
#ifndef MAINFRAME
scr_rowcol(1, 0);
PRINT
"X = %.12g Y = %.12g \n", xval, yval);
PRINT
"This point is too far from screen: more than %g diameters from the screen\n",
diameters[ScrnSec]);
PRINT
"Program now enters SINGLE STEP mode to prevent overflow\n");
PRINT
"Reinitialize using 'i' or 'm' or cursor keys and/or reset menu's parameters\n"
);
PRINT
"\nTo change 'diameters', return to menu(hit space bar) and enter P then SD\n"
);
#endif /* MAINFRAME */
cycle = 2; /* single step mode; setting cycle = 2 tells
Interrupt() not to call plot() since that
would give an infinite loop */
Interrupt();
return;
}
/* -------------------------------------------------------------------- */
/* CLRWINDOW - clear a section of the window. */
clrWindow()
{
stoplines(); /* for stopping drawing connected lines */
SignIsOn = 0; /* sign about jump size */
IsCross0Set = NO; /* screen cross at y0 is not set */
IsCross1Set = NO; /* screen cross at y1 is not set */
turnoff(BIGCROSS);
turnoff(SMALLCROSS);
if(ScrnSec == 0) {
scr_clr();
}
else if(ScrnSec == 1) {
picOff(0, 0, corecols / 2, corerows / 2);
scrOff(0, 0, scrncols / 2, scrnrows / 2);
}
else if(ScrnSec == 2) {
picOff(corecols / 2, 0, corecols, corerows / 2);
scrOff(scrncols / 2, 0, scrncols, scrnrows / 2);
}
else if(ScrnSec == 3) {
picOff(0, corerows / 2, corecols / 2, corerows);
scrOff(0, scrnrows / 2, scrncols / 2, scrnrows);
}
else if(ScrnSec == 4) {
picOff(corecols / 2, corerows / 2, corecols, corerows);
scrOff(scrncols / 2, scrnrows / 2, scrncols, scrnrows);
}
return;
}
/* -------------------------------------------------------------------- */
/* TICGAP - return distance between tic marks; input difference between left
* and right scales; returns a number starting with a digit 5,6,7,8, or 9;
* Hence .0056... returns .005, and -.0056 becomes -.005; if first digit
* is 1, number is multiplied by 5; if first digit is less than 5, number
* is multiplied by 2.
*/
double ticGap(dif)
double dif;
{
double old = dif; /* keeps track of change in size of dif */
if(dif == 0.0)
return(0.0);
if(dif < 0.0)
dif = -dif;
while(dif < 1.0)
dif *= 10.0;
while(dif > 10)
dif /= 10.0;
if(dif < 2.0)
dif *= 5.0;
if(dif < 5.0)
dif *= 2.0;
return(old / dif);
}
/* -------------------------------------------------------------------- */
/* TICMARKS - draw the tick marks. FLAG == 2 means that an extra fine
* set of tic marks should be drawn with 1/5 the spacing. This extra set
* is small and will show up better when the picture is printed.
*/
ticMarks(flag)
int flag;
{
int size, j, ntic, ticlen; /* TICLEN is in pixels */
double gap, x, v;
POINT *p;
XSegment *ticlist, *tp; /* indexes ticlist */
scr_rowcol(2, 0);
size = (flag == 2 ? 170 : 100);
if((gap = ticGap(X_upp - X_low)) == 0.0) {
PRINT "CANNOT DRAW TIC MARKS; BOX HAS 0 WIDTH \n");
return;
}
if(flag == 2)
gap /= 5.0;
/* moduloAB() is a number between 0 and GAP -- even if GAP
* is negative.
*/
x = X_low - moduloAB(X_low, 0.0, gap) + gap;
x += gap * 0.000001;
erase_line();
PRINT "Horizontal spacing between tic marks: %g starting at %g\n",
gap, x);
ntic = (int) (fabs(X_upp - x) / fabs(gap));
tp = ticlist
= (XSegment *) malloc((unsigned) ntic * 2 * sizeof(XSegment));
ticlen = scrnrows / size;
/* Store tics as small segments which we plot in one call.
* First do the ones along the bottom axis.
*/
for(j = 0; j < ntic; j++) {
if((p = FindPixel(x + j * gap, Y_low, SCRN)) != NULL) {
tp->x1 = tp->x2 = p->x;
tp->y1 = p->y;
tp->y2 = p->y - ticlen;
tp++;
}
}
/* Now do the ones along the top */
for(j = 0; j < ntic; j++) {
if((p = FindPixel(x + j * gap, Y_upp, SCRN)) != NULL) {
tp->x1 = tp->x2 = p->x;
tp->y1 = p->y;
tp->y2 = p->y + ticlen;
tp++;
}
}
/* Display the tick marks along the X direction. */
XDrawSegments(x_dpy, x_window, x_gc, ticlist, (int) (tp - ticlist));
/* Repeat for the tick marks along the Y axis */
if((gap = ticGap(Y_upp - Y_low)) == 0.0) {
PRINT "CANNOT DRAW TIC MARKS; BOX HAS 0 HEIGHT \n");
return;
}
if(flag == 2)
gap /= 5.0;
v = Y_low - moduloAB(Y_low, 0., gap) + gap;
v = v + gap * 0.000001;
PRINT "Vertical spacing between tic marks: %g starting at %g\n",
gap, v);
j = (int) (fabs(Y_upp - v) / fabs(gap));
if(j > ntic) {
ntic = j;
ticlist = (XSegment *) realloc((char *) ticlist,
(unsigned) ntic * 2 * sizeof(XSegment));
}
/* Now do the tick marks on the right */
tp = ticlist;
for(j = 0; j < ntic; j++) {
if((p = FindPixel(X_upp, v + j * gap, SCRN)) != NULL) {
tp->y2 = tp->y1 = p->y;
tp->x1 = p->x;
tp->x2 = p->x - ticlen;
tp++;
}
}
/* Now do the tick marks on the left */
for(j = 0; j < ntic; j++) {
if((p = FindPixel(X_low, v + j * gap, SCRN)) != NULL) {
tp->y2 = tp->y1 = p->y;
tp->x1 = p->x;
tp->x2 = p->x + ticlen;
tp++;
}
}
/* Display the tick marks along the Y direction. */
XDrawSegments(x_dpy, x_window, x_gc, ticlist, (int) (tp - ticlist));
free((char *) ticlist);
return;
}
/* -------------------------------------------------------------------- */
/* CONNECT2 - connect (xval, yval) to (xval2, yval2).
*/
connect2(xval, yval, xval2, yval2)
double xval, yval, xval2, yval2;
{
POINT from, *p;
/* Erase big cross temporarily so we store contents of line if
* the line intersects the region obscured by the box circumscribing
* the cross.
*/
if(cross0flag)
turnoff(BIGCROSS);
if((p = FindPixel(xval, yval, SCRN)) != NULL) {
from = *p;
if((p = FindPixel(xval2, yval2, SCRN)) != NULL)
XDrawLine(x_dpy, x_window, x_gc, from.x, from.y, p->x,
p->y);
else
checkiterate(xval2, yval2);
} else
checkiterate(xval, yval);
if(cross0flag) /* turn the big cross back on again */
SetCross(BIGCROSS);
stoplines(); /* for stopping drawing connected lines */
return;
}
/* -------------------------------------------------------------------- */
/* CONNECTP - connect (x,y) to the previously drawn point. The screen
* coordinates of the previously drawn point are pointed to by STARTPT.
* If STARTPT is NULL, then line drawing has been turned off, so we
* do nothing.
*/
connectp(xval, yval)
double xval, yval;
{
static POINT lastpt; /* endpoint of last segment drawn */
POINT *p;
/* If the point is out of bounds, check that it is not so far
* away that we're about to blow up.
*/
if((p = FindPixel(xval, yval, SCRN)) == NULL) {
checkiterate(xval, yval);
stoplines(); /* for stopping drawing connected lines */
}
/* In case we just did a modulo operation, or if line drawing has
* been turned off, then don't plot any lines.
*/
else {
if(startpt != NULL && modFlag == NO)
XDrawLine(x_dpy, x_window, x_gc, startpt->x,
startpt->y, p->x, p->y);
lastpt = *p;
startpt = &lastpt; /* prime the pump */
}
return;
}
/* -------------------------------------------------------------------- */
/* SCROFF - blank out the indicated region in screen coordinates */
scrOff(COLnum1, ROWnum1, COLnum2, ROWnum2)
int COLnum1, ROWnum1, COLnum2, ROWnum2;
{
int width = COLnum2 - COLnum1;
int height = ROWnum2 - ROWnum1;
if(width > 0 && height > 0)
XFillRectangle(x_dpy, x_window, x_gcblank, COLnum1, ROWnum1,
(unsigned) width, (unsigned) height);
return;
}
/* -------------------------------------------------------------------- */
/* PICOFF - blank out the indicated region in the core copy of the picture */
/* Note: this is a no-op for now. */
picOff(COLnum1, ROWnum1, COLnum2, ROWnum2)
{
return;
}
/* -------------------------------------------------------------------- */
/* BLOCK_PLOT - fill the rectangle whose corner points are given by
* (xval, yval) and (xval2, yval2). Both points MUST be visible on the screen;
* otherwise no rectangle is drawn.
*/
block_plot(xval, xval2, yval, yval2)
double xval, xval2, yval, yval2;
{
POINT *p, from;
int width, height;
if((p = FindPixel(xval, yval, SCRN)) != NULL) {
from = *p;
if((p = FindPixel(xval2, yval2, SCRN)) != NULL) {
width = p->x - from.x;
height = p->y - from.y;
XFillRectangle(x_dpy, x_window, x_gc, from.x, from.y,
(unsigned) width, (unsigned) height);
}
}
return;
}
/* -------------------------------------------------------------------- */
/* BOTTOMPRINT - print list of interrupts. */
bottomPrint()
{
#ifndef MAINFRAME
scr_rowcol(21, 0); /* move cursor to bottom left; */
PRINT
"Type * for detailed help. \n");
PRINT
"Type ? for description of INTERRUPTS; hit 2 to reduce unnecessary printing \n"
);
PRINT
"KEYBOARD INTERRUPTS: space q ? r c C l p m t T 0 1 2 3 4 5 e E P + - F5..F9"
);
PRINT "\n");
PRINT
"cross KEYBOARD INTERRUPTS: %c%c%c%c b B C i I w s u x X y Y F1..F4 F10 k K O\n"
,UPARROW, DNARROW, LTARROW, RTARROW);
scr_rowcol(0, 0); /* move cursor to top left; */
#endif /* MAINFRAME */
}
/* -------------------------------------------------------------------- */
/* DRAW_BOX - draw a box with x coordinates X_low,X_upp
* and y coordinates Y_low,Y_upp.
*/
draw_box()
{
int width, height; /* of rectangle */
POINT origin, *dest;
double X_small,
Y_small;
/* set_box() sets X_low thru Y_upp; set_box ==
* 0 if box is partially outside window.
*/
if(set_box() != 0 && ticFlag != OFF)
ticMarks(ticFlag);
PrintBoxCoordinates(); /* if printer > 1 */
Y_small = 0.00001 * (Y_upp - Y_low);
X_small = 0.00001 * (X_upp - X_low);
if((dest = FindPixel(X_low + X_small, Y_low + Y_small, SCRN)) != NULL) {
origin = *dest;
if((dest = FindPixel(X_upp - X_small, Y_upp - Y_small, SCRN))
!= NULL) {
width = dest->x - origin.x;
height = dest->y - origin.y;
XDrawRectangle(x_dpy, x_window, x_gc, origin.x,
origin.y, (unsigned) width, (unsigned) height);
}
}
stoplines(); /* for stopping drawing connected lines */
return;
}
/* -------------------------------------------------------------------- */
PrintBoxCoordinates() /* if printer > 1 */
{
scr_rowcol(20, 0);
if(printer > 1) {
set_box(); /* sets X_low thru Y_upp */
erase_line();
PRINT
"box coords: LEFT: %g RIGHT: %g BOTTOM: %g TOP: %g\n",
X_low, X_upp, Y_low, Y_upp);
}
return;
}
/* -------------------------------------------------------------------- */
/* ERASE_LINE - in X windows, we don't worry about messing up the graphics
* screen, so just output a newline.
*/
erase_line()
{
PRINT "\n");
}
/* -------------------------------------------------------------------- */
/* DEFINITELY_ERASE_LINE - likewise. */
definitely_erase_line()
{
PRINT "\n");
}
/* -------------------------------------------------------------------- */
/* MASKDEF - a no-op for now. */
maskdef(MASK)
char MASK[];
{
return;
}
/* -------------------------------------------------------------------- */
/* TD - a dummy routine for now */
td(junk)
char *junk;
{
PRINT "The TD option is not implemented yet on X windows\n");
return;
}
/* -------------------------------------------------------------------- */
/* TD0 - a dummy routine for now */
td0(junk)
char *junk;
{
PRINT "The TD0 option is not implemented yet on X windows\n");
return;
}
/* -------------------------------------------------------------------- */
/* RESETDIAMETERS - this routine resets the sets "diameters[ScrnSec]"
* when the screen is rescaled using 's' or 'u'; "diameters[ScrnSec]" is
* needed so that when the trajectory gets too far away from the region of
* interest, the process can be stopped; this prevents overflow; when
* changing the scale so that a small region can be examined, it is
* necessary to reset "diameters" to a correspondingly larger value.
*/
resetDiameters()
{
double maximum,
Xratio,
Yratio;
set_box();
Xratio = fabs((X_upp - X_low) / (X_upper - X_lower));
Yratio = fabs((Y_upp - Y_low) / (Y_upper - Y_lower));
maximum = max(1.0 / Xratio, 1.0);
if(1 / Yratio > maximum)
maximum = 1 / Yratio;
/* diameters: Let d = diameters. Recall that the big window is d
* windows above and below the screen, so if the screen in one
* coordinate(Y) runs from -1 to 1, then the big window runs from -2*d-1
* to 2*d+1, while the new presumably smaller window runs from
* -Yratio to + Yratio. The big window is (2*d +1)/Yratio times bigger
* than the
* little window; if D is the new diameter, then that must be 2D+1 times
* the little window; hence D =
* .5*[(2*d + 1)/Yratio -1] = (d + .5)maximum -.5 If d < 0, we do not
* have to change it because negative values simply means we should
* ignore it.
*/
if(diameters[ScrnSec] >= 0)
diameters[ScrnSec] = maximum * (.5 + diameters[OldScrSec]) -.5;
return;
}
/* -------------------------------------------------------------------- */
/* SET_BOX - set the for box edges X_low thru Y_upp to be x_new_low thru
* y_new_upp when they have been set(so they are not the default values);
* when they have not been set the current box edges are used: X_lower
* thru Y_upper; notice that no check is made of whether x_new_low is less
* than x_new_upp; these names are misleading since they really refer to
* left and right rather than which coordinate is less than another;
* returns: 1 if box is inside(or equal to) window 0 if outside.
*/
int set_box()
{
X_low = x_new_low;
if(X_low == -9999)
X_low = X_lower;/* equals first argument unless it is -9999, in
which case it equals the second argument */
X_upp = x_new_upp;
if(X_upp == -9999)
X_upp = X_upper;
Y_low = y_new_low;
if(Y_low == -9999)
Y_low = Y_lower;
Y_upp = y_new_upp;
if(Y_upp == -9999)
Y_upp = Y_upper;
/* test location of box */
if((X_low - X_lower) * (X_upper - X_low) < 0
|| (Y_low - Y_lower) * (Y_upper - Y_low) < 0
|| (X_upp - X_lower) * (X_upper - X_upp) < 0
|| (Y_upp - Y_lower) * (Y_upper - Y_upp) < 0) {
scr_rowcol(3, 0);
erase_line();
PRINT "Box is at least partially outside window\n");
return(0);
}
return(1);
}
/* -------------------------------------------------------------------- */
/* PPRINT - dummy routine for handling printers for now.
*/
pprint(junk)
int junk;
{
printf("Printing is not implemented yet under X windows\n");
return;
}
/* -------------------------------------------------------------------- */
int checkPrinter() /* dummy version for now */
{
return(NO);
}
/* -------------------------------------------------------------------- */
int printerStatus() /* dummy version for now */
{
return(NO);
}
#endif /* X11 */